<?php

namespace App\Http\Controllers\api\goods;

use App\Common\statement\CommonStatement;
use App\Exceptions\api\BaseException;
use App\Http\Controllers\api\base\BaseController;
use App\Http\Controllers\api\pay\PayTrait;
use App\Http\Requests\base\IdRequest;
use App\Http\Requests\goods\AddCarRequest;
use App\Http\Requests\goods\CarOrderRequest;
use App\Http\Requests\goods\CountPostageRequest;
use App\Http\Requests\goods\EditCarRequest;
use App\Http\Resources\goods\CateResource;
use App\Http\Resources\goods\GoodsCollectionPageCollection;
use App\Http\Resources\goods\GoodsDetailResource;
use App\Http\Resources\goods\GoodsEvaluatesPageCollection;
use App\Http\Resources\goods\GoodsPageCollection;
use App\Http\Resources\goods\GoodsResource;
use App\Http\Resources\goods\GoodsTopResource;
use App\Http\Resources\goods\MasterResource;
use App\Http\Resources\goods\ShopCarCollection;
use App\Http\Resources\orders\OrdersPageCollection;
use App\Models\config\Config;
use App\Models\goods\Goods;
use App\Models\goods\GoodsCate;
use App\Models\goods\GoodsCollection;
use App\Models\goods\GoodsOrder;
use App\Models\goods\GoodsShare;
use App\Models\goods\GoodsView;
use App\Models\goods\Order;
use App\Models\goods\OrderDetail;
use App\Models\goods\OrderGroup;
use App\Models\goods\ShopCar;
use App\Models\templates\Delivery;
use App\Models\User;
use App\Models\user\Address;
use App\Models\user\MoneyDetail;
use App\Services\common\App;
use App\Services\goods\GoodsService;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;

class GoodsController extends BaseController
{
    use PayTrait;

    /**
     * 商品兑换
     * @param Request $request
     * @return mixed
     */
    public function exchange(Request $request)
    {
        $goods_id = $request->goods_id;
        if(!is_numeric($goods_id)){
            return error(205);
        }
        $map['id'] = $goods_id;
        $map['status'] = 1;
        $goods = Goods::where($map)->firstOrFail();
        if(!$goods){
            return error(204);
        }
        if(($money = $this->user->money - $goods['price']) < 0){
            return error('当前积分不足');
        }
        if($goods['stock'] < 1){
            return error('商品暂无法兑换');
        }
        $params = [
            'user_id' => $this->user_id,
            'goods_id' => $goods_id,
            'integral' => $goods['price']
        ];
        DB::beginTransaction();
        try {
            $data = GoodsOrder::create($params);
            $moneyLog = MoneyDetail::create([
                'user_id' => $this->user_id,
                'amount' => $goods['price'],
                'title' => '商品兑换',
                'pm' => 0
            ]);
            $user = User::where(['id'=>$this->user_id])->update(['money'=>$money]);
            $stock = Goods::where('id',$goods_id)->decrement('stock',1);
            if(!$data || !$moneyLog || !$user || !$stock){
                DB::rollBack();
                return error('兑换失败');
            }
            DB::commit();
        }catch (\Exception $e){
            DB::rollBack();
            return error($e->getMessage());
        }
        return success($data);
    }

    /**
     * 兑换记录
     */
    public function exchangeRecord(Request $request)
    {
        $data = GoodsOrder::where('user_id',$this->user_id)->paginate();
        return success(new OrdersPageCollection($data));
    }
    
    public function getTop()
    {
        $map['is_top'] = 1;
        $map['pid'] = 0;
        $rows = GoodsCate::where($map)->limit(6)->orderByDesc('sort')->get();

        return success(new GoodsTopResource($rows));
    }


    public function getMaster(Request $request)
    {

        if (is_numeric($request->type)){
            $map['type'] = $request->type;
        }
        $map['pid'] = 0;

        $rows = GoodsCate::where($map)->orderByDesc('sort')->get();

        return success(new MasterResource($rows));
    }

//    public function getCate(GetCateRequest $request)
//    {
//        $map = [];
//
//        $sql = new GoodsCate();
//
//
//        if (is_numeric($request->type)){
//            $map1['type'] = $request->type;
//            $map1['pid'] = 0;
//
//            $sql = $sql->whereIn('pid',GoodsCate::where($map1)->pluck('id'));
//        }
//
//        if (is_numeric($request->id)) {
//            $map['pid'] = $request->id;
//        }
//
//        $rows = $sql->where($map)->orderByDesc('sort')->get();
//
//        return success(new NewsResource($rows));
//    }

    public function getAllCate()
    {
        $map = [];
        $map['pid'] = 0;
        $sql = new GoodsCate();

        $rows = $sql->where($map)->orderByDesc('sort')->with('subs')->get();

        foreach ($rows as $row){
            $row['subs'] = new CateResource($row->subs);
        }

        return success(new CateResource($rows));
    }


    protected function car($request)
    {

        $goods = Goods::with('detail', 'specs')->whereId($request->goods_id)->first();

        if (!$goods) {
            throw new BaseException("商品不存在!");
        }


        if (!empty($goods->detail->type_detail)) {
            if (empty($request->type_name)) {
                throw new BaseException("类型不能为空!");
            }

            if (mb_strpos($goods->detail->type_detail, $request->type_name) === false) {
                throw new BaseException("类型不存在!");
            }

        } else {
            if (!empty($request->type_name)) {
                throw new BaseException("商品不存在类型!");
            }
        }
        $spec = false;

        if ($goods->specs->count() >= 1) {
            foreach ($goods->specs as $v) {
                if ($v->id == $request->spec_id) {
                    $spec = $v;
                    break;
                }
            }

            if (!$spec) {
                throw new BaseException("请选择规格!");
            }
        } else {
            $request->spec_id = 0;
        }

        $map['user_id'] = $this->user_id;
        $map['type_name'] = $request->type_name??'';
        $map['spec_id'] = $request->spec_id;
        $map['goods_id'] = $request->goods_id;
        return [$map, $goods, $spec];
    }

    /**
     * 列表
     */
    public function goodsList(Request $request)
    {
        $map = [];

        if ($request->is_recommend == 1){
            $map['is_recommend'] = 1;
        }

        $sql = new Goods();

        if (!empty($request->name)){
            $map[] = ['name','like',"%{$request->name}%"];
        }

        switch ($request->sort){
            case "sale_num_desc":
                $sort = ['sale_num','desc'];
                break;
            case "sale_num":
                $sort = ['sale_num'];
                break;
            case "sort_desc":
                $sort = ['sort','desc'];
                break;
            case "price_desc":
                $sort = ['price','desc'];
                break;
            case "price":
                $sort = ['price'];
                break;
            case "created_at_desc":
                $sort = ['created_at','desc'];
                break;
            case "created_at":
                $sort = ['created_at'];
                break;
            default:
                $sort = ['sort'];
        }

        $map['status'] = 1;

        $rows = $sql->where($map)->orderBy(...$sort)->with('detail')->paginate(10);

        return success( new GoodsResource($rows));

    }

    /**
     * 详情
     */
    public function detail(IdRequest $request)
    {
        $map['id'] = $request->id;
        $map['status'] = 1;

        $goods = Goods::where($map)->with(['detail','specs','order_groups' => function($query){
            $query->where('status',0)->with('user');
        }])->firstOrFail();
//        Views::dispatch($goods);
        $c_map['user_id']  = $this->user_id;
        $c_map['goods_id'] = $goods->id;
        $c_map['status']   = 1;
        $is_collection = GoodsCollection::where($c_map)->value('status')??0;
        return success( new GoodsDetailResource( $goods,$is_collection ));

    }

    /**
     * 商品评价
     */
    public function evaluates(IdRequest $request)
    {
        $map['goods_id'] = $request->id;
        $map[] = ['evaluate','!=',''];

        if ($request->has_imgs == 1){
            $map[] = ['imgs','!=','[]'];
        }

        $rows = OrderDetail::where($map)->with('user')->paginate();
        return success( new GoodsEvaluatesPageCollection( $rows) );
    }
    


    /**
     * 查询推荐产品
     */
    public function recommend(Request $request)
    {
        $max = is_numeric(Config::getConfig('recommend')) ? Config::getConfig('recommend') : 6 ;

        $map = [];
        $map2 = [];

        $sql1 = new Goods();
        $sql2 = new GoodsView();

        if (is_numeric($request->id)){
            $goods = Goods::find($request->id);

            $map['cate1_id'] = $goods->cate1_id;
            $map2['cate1_id'] = $goods->cate1_id;
        }

        if ($this->user && $this->user->level >= 4){
            $sql1 =  $sql1->whereBetween('type',[1,2]);
            $sql2 = $sql2->whereBetween('type',[1,2]);
        }else{
            $map['type'] = 1;
            $map2['type'] = 1;
        }

        $map['status'] = 1;
        $map['is_recommend'] = 1;

        $ids1 = $sql1->where($map)->orderByDesc('sort')->limit($max*2)->pluck('id')->toArray();

        $ids2 = $sql2->where($map2)->orderByDesc('views')->limit($max*2)->pluck('goods_id')->toArray();

        $ids = array_unique(array_merge($ids1,$ids2));

        shuffle($ids);

        if (count($ids) > $max+3){
            $ids = array_slice($ids,0,$max+3);
        }

        sort($ids);
        $where[] = ['stock' ,'>',0];
        $goods = Goods::whereIn('id',$ids)->where($where)->get();

        return success( new GoodsResource($goods));

    }

    public function add(AddCarRequest $request)
    {

        list($map, $goods, $spec) = $this->car($request);

        $car = ShopCar::firstOrNew($map);

        if ($car->id) {
            $car->num += $request->num;
        } else {
            $car->num = $request->num;
        }

        $result = $car->save();

        if ($result) {
            return successWithMsg("添加成功",[
                'num'=>$car->num,
                'id'=>$car->id,
                'price'=>getPrice($car,$this->user)
            ]);
        }

        return error();
    }


    public function carList()
    {
        $rows = ShopCar::whereUserId($this->user_id)->where('num','!=',0)->with('goods', 'spec')->get();

        return success(  new ShopCarCollection($rows,$this->user));

    }

    public function edit(EditCarRequest $request)
    {
        $map['user_id'] = $this->user_id;
        $map['id'] = $request->id;

        $car = ShopCar::where($map)->firstOrFail();


        if (!is_null($request->checked)){
            $car->checked = $request->checked;
        }

        if (!is_null($request->num)){
            $car->num = $request->num;
        }
        if ($car->num == 0) {
            $result = $car->delete();
        } else {
            $result = $car->save();
        }

        if ($result) {
            return success();
        }

        return error();
    }

    /**
     * 购物车批量删除
     * @param Request $request
     * @return mixed
     */
    public function delete(Request $request)
    {
        if (empty($request->ids)) {
            return error("ID不能为空!");
        }

        $id = explode(',', $request->ids);

        $result = ShopCar::whereUserId($this->user_id)->whereIn('id', $id)->delete();

        if ($result) {
            return successWithMsg("删除成功");
        }
        return error();
    }

    /**
     * 商品收藏或取消
     */
    public function collection(IdRequest $request)
    {
        $map['goods_id'] = $request->id;
        $map['user_id'] = $this->user_id;

        $collection = GoodsCollection::firstOrNew($map);
        if ($collection->id) {
            if ($collection->status == 1){
                $collection->status = 0;
            }else{
                $collection->status = 1;
            }
        } else {
            $collection->status = 1;
        }
        $result = $collection->save();

        if ($result){
            return successWithMsg("操作成功");
        }

        return error();

    }


    /**
     * 我的收藏商品
     */
    public function collections()
    {
        $map['user_id'] = $this->user_id;
        $map['status']  = 1;

        $rows = GoodsCollection::where($map)
            ->whereHas('goods', function ($query) {
                $query->where('status',1);
            })
            ->with('goods')
            ->latest('updated_at')
            ->paginate();

        return success( new GoodsCollectionPageCollection($rows));

    }

    public function carOrder(CarOrderRequest $request)
    {

        $remark = json_decode($request->remark, true);

        $ids = explode(',', $request->id);

        $cars = ShopCar::whereUserId($this->user_id)->whereIn('id', $ids)->with('spec', 'goods')->get();

        if ($cars->isEmpty()) {
            return error("购物车为空!");
        }

        return $this->order($cars, $request->address_id, $remark, $request);

    }

    public function makeOrder(AddCarRequest $request)
    {

        list($map, $goods, $spec) = $this->car($request);

        $car = ShopCar::newModelInstance($map);
        $car->num = $request->num;
        //方便购物车注释添加
        $car->id = 0;
        $remark[0] = $request->remark;
        return $this->order(collect([$car]),$request->address_id,$remark,$request);
    }

    /**
     *  获取邮费
     */
    public function countPostage(CountPostageRequest $request)
    {
        $map['id'] = $request->id;
        $address = Address::where($map)->firstOrFail();
        $ids = explode(',',$request->ids);
//        $goodses = Goods::whereIn('id',$ids)->get();
        $prices = [];
        $nums = explode(',',$request->nums);

        if (count($ids) != count($nums)){
            return error("商品数量与购买数量不匹配");
        }

        foreach ($ids as $k => $id){
            $goods = Goods::findOrFail($id);
            $prices[] = $this->getPostage($goods,$nums[$k],$address);
        }

        return success(  $prices );
    }


    protected function getPostage(Goods $goods ,$num,Address $address)
    {
        $postage = 0;
        if ($goods->detail->delivery_id) {
            if (!$inRegion = $goods->detail->delivery->checkAddress($address->c_id)) {
                return error(CommonStatement::notInRegion);
            }
            $goods_total_weight = bcmul($goods->detail->weight, $num, 2);
            $postage = $goods->detail->delivery->calcTotalFee($num,$goods_total_weight,$address->c_id);
        }
        return $postage;
    }

    protected function order($cars,$address_id,$remark,$request)
    {

        $total_price = 0;

        $map['id'] = $address_id;
        $address = Address::where($map)->firstOrFail();
        $payInfo = '';

        $order['old_price'] = 0;

        $postageTotal = 0;

        $delete_ids = [];

        \DB::beginTransaction();
        try {

            $details = [];
            foreach ($cars as $car){

                if ($car instanceof ShopCar);
                $delete_ids[] = $car->id;
                $detail = [];

                $postage = $this->getPostage($car->goods,$car->num,$address);

                if (isset($remark[$car->id])){
                    $detail['remark'] = $remark[$car->id];
                }else{
                    $detail['remark'] = '';
                }

                $postageTotal += $postage;

                $detail['postage'] = $postage;
                $detail['pay_info'] = '';
                $detail['goods_id'] = $car->goods_id;
                $detail['type_name'] = $car->type_name ?? '';
                $detail['spec'] = $car->spec->name ?? '';
                $detail['spec_alias'] = $car->spec->alias ?? '';
                $detail['num'] = $car->num;

                if ($car->spec){
                    $detail['old_price'] = bcmul($car->spec->price, $detail['num'], 2);
                }else{
                    $detail['old_price'] = bcmul($car->goods->price, $detail['num'], 2);
                }

                $order['old_price'] = bcadd($detail['old_price'],$order['old_price'],2);

                list($detail['price'],$detail['price_field']) = getPrice($car,$this->user,true);

                if ($request->is_pt && $car->goods->is_pt){//拼团处理
                    if ($request->order_group_id){//加入拼团
                        $o_map['user_id'] = $this->user_id;
                        $o_map['order_group_id'] = $request->order_group_id;
                        $g_has = Order::where($o_map)->first();
                        if ($g_has){
                            return error("您已加入此拼团!");
                        }
                        $group = OrderGroup::findOrFail($request->order_group_id);
                        if ($group->status != 0){
                            return error("拼团已结束!");
                        }

                        $group->num ++;

                        if ($group->num > $group->total){
                            //拼团人数满之后的订单处理
//                            GroupQueue::dispatch($group->id)->delay(Carbon::now()->addSeconds(3));
                            return error("拼团人数已满!");
                        }
                        $group->status = 1;

                        $group->save();

                        $order['order_group_id'] = $request->order_group_id;
                    }else{
                        $g_map['goods_id'] = $car->goods_id;
                        $g_map['user_id'] = $this->user_id;
                        $g_map['status'] = 0;
                        $og_has = OrderGroup::where($g_map)->first();
                        if ($og_has){
                            return error("您还有正在拼团中的订单,请勿重复操作!");
                        }

                        $g_map['total'] = $car->goods->detail->pt_num;
                        $g_map['num']   = 1;
                        $og = OrderGroup::create($g_map);
                        $order['order_group_id'] = $og->id;
                        //拼团人数满之后的订单处理
//                        GroupQueue::dispatch($og->id)->delay(Carbon::now()->addSeconds(3));
                    }

                    $detail['price_field'] = 'pt_price';
                    if ($car->spec){
                        $detail['price'] =  $car->spec->pt_price;
                    }else{
                        $detail['price'] =  $car->goods->detail->pt_price;
                    }

                }

                $detail['total_price'] = bcmul($detail['price'], $detail['num'], 2);
                $detail['total_price'] = bcadd($postage,$detail['total_price'],2);
                $detail['goods_name'] = $car->goods->name??'';
                $detail['goods_alias'] = $car->goods->alias??'';
                $detail['goods_img']  = $car->goods->img??'';
                $detail['user_id'] = $car->user_id;
                $total_price = bcadd($total_price,$detail['total_price'],2);

                $details[] = $detail;

            }

            $order['is_safe'] = $request->is_safe??0;

            if ($order['is_safe'] == 1){//增加一元总价
                $total_price = bcadd($total_price,1,2);
            }

            $order['total_price'] = $total_price;
            $order['user_id'] = $this->user_id;

            $order['detail'] = " {$address->p_name} {$address->c_name} {$address->d_name} {$address->detail}";
            $order['phone'] = $address->phone;
            $order['user_name'] = $address->name;

            $order['pay_info'] = $payInfo;
            $order['postage'] = $postageTotal;
            if ($order['money']) {
                $this->user->decrement('money', $order['money']);
                if ($order['money'] >= $order['total_price']) { //是否付款
                    $order['status'] = 1;
                }
            }

            $order['order_no'] = $this->prefix.date('ymdHis'). getMinUid($this->user_id);

            $obj =  Order::create($order);

            foreach ($details as $k => $v){
                $details[$k]['order_id'] = $obj->id;
            }

            OrderDetail::insert($details);

            if (!empty($delete_ids)){
                ShopCar::whereIn('id',$delete_ids)->delete();
            }

            \DB::commit();
        } catch (\Exception $e) {
            \DB::rollBack();
            return error($e->getMessage());
        }

        $data['order_id'] = $obj->id;
        $data['is_pay']    = 1;

        return successWithMsg("下单成功",$data);

    }



    public function pay(IdRequest $request)
    {
        $map['id'] = $request->id;
        $map['user_id'] = $this->user_id;
        $map['status'] = 0;
        $order = Order::where($map)->firstOrFail();
        if ($this->user->money < $order->total_price){
            return error("余额不足!");
        }

        DB::beginTransaction();
        try {

            $order->status = 1;
            $order->money = $order->total_price;
            $order->pay_info = $order->pay_info.sprintf("余额支付%s元;",$order->total_price);

            $order->save();
            $this->user->decrement('money',$order->total_price);

            DB::commit();
        }catch (\Exception $e){
            DB::rollBack();
            return error($e->getMessage());
        }
        return successWithMsg("付款成功!");
    }


    /**
     * 删除订单
     */
    public function del(IdRequest $request)
    {
        $map['user_id'] = $this->user_id;
        $map['id'] = $request->id;

        $order = Order::where($map)->firstOrFail();

        //可删除订单
        $arr = [
            -1,
            3,
            4,
            5,
        ];
        if (!in_array($order->status, $arr)) {
            return error("订单不可删除!");
        }

        $result = $order->delete();
        if ($result) {
            return successWithMsg("删除成功");
        }
        return error("删除失败");


    }


    public function shareCallback(IdRequest $request)
    {

        $map['user_id'] = $this->user_id;
        $all_count = GoodsShare::where($map)->whereDate('created_at',date('Y-m-d'))->count();

        $get = true;
        if ($all_count >= Config::getConfig('share_all_date_max')){
            $get = false;
//            return error(CommonStatement::job_default);
        }

        $map['goods_id'] = $request->id;

        $goods_count = GoodsShare::where($map)->whereDate('created_at',date('Y-m-d'))->count();

        if ($goods_count >= Config::getConfig('share_goods_date_max')){
            $get = false;
//            return error(CommonStatement::job_default);
        }

        DB::beginTransaction();
        try {

            GoodsShare::create($map);

            if ($get === true)
            {
                $coin = Config::getConfig('share_goods_coin');
                moneyDetailAdd($this->user_id,$coin,'分享商品');
                User::whereId($this->user_id)->increment('money',$coin);
            }

            DB::commit();
        }catch (\Exception $e){
            DB::rollBack();
            return error($e->getMessage());
        }
        if ($get === true && $coin){
            return successWithMsg("分享商品成功,获得奖励[{$coin}]");
        }
        return successWithMsg("分享商品成功");

    }







}
